#include "../advanced_cfg.h"
#include "../advanced_cfg.h"
#include <hld/pdd/power_down_detect.h>
static AdvanceCfgPara g_cfg_para; 

#ifdef HDTV_SUPPORT
static void avc_attach(void)
{
#if((!defined _S3281_)||(!defined _BUILD_OTA_E_))//add by comer
    struct vdec_avc_config_par vdec_avc_cfg;
    
	MEMSET(&vdec_avc_cfg, 0, sizeof(struct vdec_avc_config_par));   
    vdec_avc_cfg.max_additional_fb_num = MAX_EXTRA_FB_NUM;
    vdec_avc_cfg.memmap.support_multi_bank = g_cfg_para.h264_support_mulit_bank;  //H264_SUPPORT_MULTI_BANK
 /*   if(g_cfg_para.chanchg_video_type_support)                                     //CHANCHG_VIDEOTYPE_SUPPORT
    {
    	vdec_avc_cfg.memmap.support_conti_memory = 0;
    	if(vdec_avc_cfg.memmap.support_conti_memory==0)
    	{
    		vdec_avc_cfg.memmap.frame_buffer_base = AVC_FB_ADDR;
    		vdec_avc_cfg.memmap.frame_buffer_len = AVC_FB_LEN;
    		vdec_avc_cfg.memmap.dv_frame_buffer_base = AVC_DVIEW_ADDR;
    		vdec_avc_cfg.memmap.dv_frame_buffer_len = AVC_DVIEW_LEN;
    		vdec_avc_cfg.memmap.mv_buffer_base = AVC_MV_ADDR;
    		vdec_avc_cfg.memmap.mv_buffer_len = AVC_MV_LEN;
    		vdec_avc_cfg.memmap.mb_col_buffer_base = AVC_MB_COL_ADDR;
    		vdec_avc_cfg.memmap.mb_col_buffer_len = AVC_MB_COL_LEN;
    		vdec_avc_cfg.memmap.mb_neighbour_buffer_base = AVC_MB_NEI_ADDR;
    		vdec_avc_cfg.memmap.mb_neighbour_buffer_len = AVC_MB_NEI_LEN;
    		vdec_avc_cfg.memmap.cmd_queue_buffer_base = AVC_CMD_QUEUE_ADDR;
    		vdec_avc_cfg.memmap.cmd_queue_buffer_len = AVC_CMD_QUEUE_LEN;
    		//vdec_avc_cfg.memmap.vbv_buffer_base = 0x84000000;
    		//vdec_avc_cfg.memmap.vbv_buffer_len = 0x1000000;
    		//  vdec_avc_cfg.memmap.vbv_buffer_base = (0xa7000000);//(AVC_VBV_ADDR & 0x0fffffff) | 0x80000000;
    		// vdec_avc_cfg.memmap.vbv_buffer_len = 0x400000; //AVC_VBV_LEN;
    		vdec_avc_cfg.memmap.vbv_buffer_base = (AVC_VBV_ADDR & 0x0fffffff) | 0x80000000;
    		vdec_avc_cfg.memmap.vbv_buffer_len = 0x300000;
    		vdec_avc_cfg.memmap.laf_rw_buf = AVC_LAF_RW_BUF_ADDR;
    		vdec_avc_cfg.memmap.laf_rw_buffer_len = AVC_LAF_RW_BUF_LEN;
    		vdec_avc_cfg.memmap.laf_flag_buf = AVC_LAF_FLAG_BUF_ADDR;
    		vdec_avc_cfg.memmap.laf_flag_buffer_len = AVC_LAF_FLAG_BUF_LEN;
    	}
    	else
    	{
    		vdec_avc_cfg.memmap.vbv_buffer_base = (AVC_VBV_ADDR & 0x0fffffff) | 0x80000000;
    		vdec_avc_cfg.memmap.vbv_buffer_len = 0x300000;
    		vdec_avc_cfg.memmap.cmd_queue_buffer_base = vdec_avc_cfg.memmap.vbv_buffer_base - AVC_CMD_QUEUE_LEN;
    		vdec_avc_cfg.memmap.cmd_queue_buffer_len = AVC_CMD_QUEUE_LEN;
    		vdec_avc_cfg.memmap.mb_col_buffer_base = vdec_avc_cfg.memmap.cmd_queue_buffer_base - AVC_MB_COL_LEN;
    		vdec_avc_cfg.memmap.mb_col_buffer_len = AVC_MB_COL_LEN;
    		vdec_avc_cfg.memmap.mb_neighbour_buffer_base = vdec_avc_cfg.memmap.mb_col_buffer_base - AVC_MB_NEI_LEN;
    		vdec_avc_cfg.memmap.mb_neighbour_buffer_len = AVC_MB_NEI_LEN;
    		vdec_avc_cfg.memmap.avc_mem_len = AVC_MEM_LEN;
    		vdec_avc_cfg.memmap.avc_mem_addr = vdec_avc_cfg.memmap.mb_neighbour_buffer_base - vdec_avc_cfg.memmap.avc_mem_len;
    	}
    }
    else*/ if(g_cfg_para.avc_unify_mem_support)  //AVC_SUPPORT_UNIFY_MEM
    {
    	vdec_avc_cfg.memmap.support_conti_memory = 1;   	
    	vdec_avc_cfg.memmap.vbv_buffer_base = (AVC_VBV_ADDR & 0x0fffffff) | 0x80000000;
    	vdec_avc_cfg.memmap.vbv_buffer_len = AVC_VBV_LEN;
    	vdec_avc_cfg.memmap.cmd_queue_buffer_base = vdec_avc_cfg.memmap.vbv_buffer_base - AVC_CMD_QUEUE_LEN;
    	vdec_avc_cfg.memmap.cmd_queue_buffer_len = AVC_CMD_QUEUE_LEN;
    	vdec_avc_cfg.memmap.mb_col_buffer_base = vdec_avc_cfg.memmap.cmd_queue_buffer_base - AVC_MB_COL_LEN;
    	vdec_avc_cfg.memmap.mb_col_buffer_len = AVC_MB_COL_LEN;
    	vdec_avc_cfg.memmap.mb_neighbour_buffer_base = vdec_avc_cfg.memmap.mb_col_buffer_base - AVC_MB_NEI_LEN;
    	vdec_avc_cfg.memmap.mb_neighbour_buffer_len = AVC_MB_NEI_LEN;
    	vdec_avc_cfg.memmap.avc_mem_len = AVC_MEM_LEN;
    	vdec_avc_cfg.memmap.avc_mem_addr = vdec_avc_cfg.memmap.mb_neighbour_buffer_base - vdec_avc_cfg.memmap.avc_mem_len;
    }
    else
    {
        vdec_avc_cfg.memmap.frame_buffer_base = AVC_FB_ADDR;
        vdec_avc_cfg.memmap.frame_buffer_len = AVC_FB_LEN;
        vdec_avc_cfg.memmap.dv_frame_buffer_base = AVC_DVIEW_ADDR;
        vdec_avc_cfg.memmap.dv_frame_buffer_len = AVC_DVIEW_LEN;        
        vdec_avc_cfg.memmap.mv_buffer_base = AVC_MV_ADDR;
        vdec_avc_cfg.memmap.mv_buffer_len = AVC_MV_LEN;
        vdec_avc_cfg.memmap.mb_col_buffer_base = AVC_MB_COL_ADDR;
        vdec_avc_cfg.memmap.mb_col_buffer_len = AVC_MB_COL_LEN;
        vdec_avc_cfg.memmap.mb_neighbour_buffer_base = AVC_MB_NEI_ADDR;
        vdec_avc_cfg.memmap.mb_neighbour_buffer_len = AVC_MB_NEI_LEN;
        vdec_avc_cfg.memmap.cmd_queue_buffer_base = AVC_CMD_QUEUE_ADDR;
        vdec_avc_cfg.memmap.cmd_queue_buffer_len = AVC_CMD_QUEUE_LEN;
        //vdec_avc_cfg.memmap.vbv_buffer_base = 0x84000000;
        //vdec_avc_cfg.memmap.vbv_buffer_len = 0x1000000;      
        vdec_avc_cfg.memmap.vbv_buffer_base = (AVC_VBV_ADDR & 0x0fffffff) | 0x80000000;
        vdec_avc_cfg.memmap.vbv_buffer_len = AVC_VBV_LEN;
        vdec_avc_cfg.memmap.laf_rw_buf = AVC_LAF_RW_BUF_ADDR;
        vdec_avc_cfg.memmap.laf_rw_buffer_len = AVC_LAF_RW_BUF_LEN;
        vdec_avc_cfg.memmap.laf_flag_buf = AVC_LAF_FLAG_BUF_ADDR;
        vdec_avc_cfg.memmap.laf_flag_buffer_len = AVC_LAF_FLAG_BUF_LEN;

    /*  if(AVC_LAF_FLAG_BUF_ADDR < __MM_BUF_PVR_TOP_ADDR)
        {
            libc_printf("no enough buffer for AVC");
            ASSERT(0);
        }
    */
    }
/*  if(__MM_PVR_BFFUER_END < __MM_BUF_TOP_ADDR)
    {
        libc_printf("no enough buffer for stack __MM_PVR_BFFUER_END = 0x%x,__MM_BUF_TOP_ADDR = 0x%x\n",
            __MM_PVR_BFFUER_END,
            __MM_BUF_TOP_ADDR);
        ASSERT(0);
    }
*/
#ifndef _BUILD_OTA_E_
	//print_memory_layout();
#endif

    vdec_avc_cfg.dtg_afd_parsing = g_cfg_para.afd_scale_support;
    
    vdec_avc_attach(&vdec_avc_cfg);
#endif
}


#if 0 //def HDCP_FROM_CE
/********************************************************************************
*				Pls follow the release rule as following									*
*	when want to release code or bin file to customer									*
*	1. Set the vendor name, and product description  									*
*	2. Assigned the gpio pin number for AT88SC0404C I2C_SCL and I2C_SDA  				*
*	3. For mass production, customer should assigned password( 3 bytes ) 					*
*         and Secret Seed ( 8 bytes ) array. 												*
*	    The assigned password/secret seed value should be the same with programmed in		*
*	    AT88SC0404C crypto memory.							 						*
*	   For piolt production, please leave these point to NULL								*
*********************************************************************************/
static RET_CODE ce_generate_hdcp()
{
	UINT16 i,j;
	UINT32 id = HDCPKEY_CHUNK_ID;
	UINT32 hdcp_chunk;
	UINT8 *hdcp_internal_keys;
	UINT8 temp_data[16];

	CE_DATA_INFO Ce_data_info ;
	pOTP_PARAM opt_info;
	pCE_DEVICE ce_dev = (pCE_DEVICE)dev_get_by_type(NULL, HLD_DEV_TYPE_CE);
	CE_DEBUG_KEY_INFO	ce_param;

	opt_info = MALLOC(sizeof(OTP_PARAM));
	MEMSET(opt_info ,0 , sizeof(OTP_PARAM) );
	
	opt_info->otp_addr = OTP_ADDESS_4; // load m2m2
	opt_info->otp_key_pos = KEY_0_3;
	
	if( RET_SUCCESS != ce_key_load(ce_dev , opt_info))
	{
		FREE( opt_info );
		return !RET_SUCCESS;	
	}

				
	hdcp_internal_keys = (UINT8 *)MALLOC(sizeof(UINT8)*288);
	hdcp_chunk = (UINT32)sto_chunk_goto(&id,0xFFFFFFFF,1);
	sto_get_data( (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0), hdcp_internal_keys,
		hdcp_chunk+ CHUNK_HEADER_SIZE, 288);
	for(i=0;i<18;i++)
	{
		MEMCPY(temp_data,(hdcp_internal_keys+i*16),16);

		MEMCPY(&(Ce_data_info.otp_info),opt_info,sizeof(OTP_PARAM));
		Ce_data_info.data_info.data_len 				= 16;
		Ce_data_info.des_aes_info.aes_or_des 		= CE_SELECT_AES ; 	
		Ce_data_info.des_aes_info.crypt_mode 		= CE_IS_DECRYPT; 	
		Ce_data_info.des_aes_info.des_low_or_high 	= 0;					
		Ce_data_info.key_info.first_key_pos 			= KEY_0_3;
		Ce_data_info.key_info.hdcp_mode 			= TARGET_IS_HDCP_KEY_SRAM; 
		Ce_data_info.key_info.second_key_pos 		= i; 
		MEMCPY(Ce_data_info.data_info.crypt_data,temp_data,16);
	
		if(RET_SUCCESS != ce_generate_single_level_key(ce_dev, &Ce_data_info))
		{
			FREE( opt_info );
			FREE(hdcp_internal_keys);
			return !RET_SUCCESS;
		}
#if 0//for debug
		ce_param.len = 4; 
		ce_param.sel = HDCP_KEY_READ ;
		ce_ioctl(ce_dev,IO_CRYPT_DEBUG_GET_KEY,&ce_param);  
		osal_task_sleep(100);
		libc_printf("hdcp %08x,%08x,%08x,%08x\n",ce_param.buffer[0],ce_param.buffer[1],ce_param.buffer[2],ce_param.buffer[3]);
#endif
	}

	FREE( opt_info );
	FREE(hdcp_internal_keys);
	return RET_SUCCESS;
}
#endif



//static void get_hdmi_config(struct config_hdmi_parm *hdmi_param)


#endif


static void deca_dev_attach(void)
{
#if((!defined _S3281_)||(!defined _BUILD_OTA_E_))//add by comer
    struct deca_feature_config deca_config;
	MEMSET(&deca_config, 0, sizeof(struct deca_feature_config));   
	deca_config.support_desc = g_cfg_para.audio_description_support;   
	/* support dynamic sample rate change by default*/
	deca_config.detect_sprt_change = 1; 
	deca_m3327_attach(&deca_config);
	deca_ext_dec_enable((struct deca_device * )dev_get_by_id(HLD_DEV_TYPE_DECA, 0), &deca_config);

    #ifdef SPRT_CHG_DETECT
	    need_detect_sprt_chg = 1;
     #endif
#endif
}
void pok_attach()
{
#if((!defined _S3281_)||(!defined _BUILD_OTA_E_))//add by comer
	struct snd_mute_par  snd_pok_mute;
    snd_pok_mute.mute_num = g_cfg_para.sys_mute_gpio;
	snd_pok_mute.mute_polar = g_cfg_para.sys_mute_polar;
#ifdef DVBC_SUPPORT		
    pdd_init(0, 0,&snd_pok_mute);
#endif    
#endif
}
static void snd_dev_attach(void)
{
#if((!defined _S3281_)||(!defined _BUILD_OTA_E_))//add by comer
	 struct snd_feature_config snd_config;
	 MEMSET(&snd_config, 0, sizeof(struct snd_feature_config));    
	snd_config.output_config.mute_num = g_cfg_para.sys_mute_gpio;
	snd_config.output_config.mute_polar 	= g_cfg_para.sys_mute_polar;
	snd_config.output_config.dac_precision = 24;
	snd_config.output_config.dac_format 	= CODEC_LEFT;
	snd_config.output_config.is_ext_dac 	= 0;
	snd_config.output_config.ext_mute_mode = g_cfg_para.ext_mute_mode;	
	snd_config.support_spdif_mute = 1;
    	snd_config.output_config.chip_type_config = g_cfg_para.snd_output_chip_type; //QFP
	snd_config.support_desc = g_cfg_para.audio_description_support;

#ifdef SUPPORT_AUDIO_DELAY
    snd_config.support_desc |= SND_SUPPORT_DDPLUS;
#endif
#if 1
	snd_m33_attach(&snd_config); 
#endif
	
	*(volatile UINT32 *)0xb80000a0 |= 1<<6;
	HAL_GPIO_BIT_DIR_SET(g_cfg_para.sys_mute_gpio, HAL_GPIO_O_DIR);
       HAL_GPIO_BIT_SET(g_cfg_para.sys_mute_gpio, snd_config.output_config.mute_polar);  
#endif
}


static void dmx_dev_attach(void)
{
    struct dmx_pre_attach_param dmx_pre_attach;
    struct dmx_feature_config dmx_config;

    MEMSET(&dmx_config, 0, sizeof(struct dmx_feature_config));
    MEMSET(&dmx_pre_attach, 0, sizeof(struct dmx_pre_attach_param));

	dmx_config.mm_map.dmx0_dma_buf = __MM_DMX_AVP_START_ADDR;
	dmx_config.mm_map.dmx1_dma_buf = __MM_DMX_REC_START_ADDR;
	dmx_config.mm_map.ts_audio_cb_len = (__MM_DMX_AUDIO_LEN/188);	
	dmx_config.mm_map.ts_video_cb_len = (__MM_DMX_VIDEO_LEN/188);
	dmx_config.mm_map.ts_pcr_cb_len = (__MM_DMX_PCR_LEN/188);
	dmx_config.mm_map.ts_ttx_cb_len = (__MM_DMX_DATA_LEN/188);
	dmx_config.mm_map.ts_common_cb_len = (__MM_DMX_SI_LEN/188); 
#ifndef _BUILD_OTA_E_
    dmx_config.mm_map.ts_united_cb_len = (__MM_DMX_REC_LEN/188);
#else
    dmx_config.mm_map.ts_united_cb_len = (0xBC000/188);//(__MM_DMX_REC_LEN/188);
#endif
	dmx_config.mm_map.total_pid_filt_num = (4+__MM_DMX_SI_TOTAL_LEN/__MM_DMX_SI_LEN);
//	dmx_config.video_bitrate_detect = 1;
	dmx_config.sync_times = 3;
    dmx_config.clock_polarity = 0;

    dmx_pre_attach.my_size = sizeof(struct dmx_pre_attach_param);
    dmx_pre_attach.dmx_ts_blk_buf1 = __MM_DMX_CPU_BLK_ADDR;
    dmx_pre_attach.dmx_ts_blk_buf2 = __MM_DMX_SEE_BLK_ADDR;
    dmx_pre_attach.dmx_ts_blk_buf1_size = __MM_DMX_BLK_BUF_LEN;
    dmx_pre_attach.dmx_ts_blk_buf2_size = __MM_DMX_BLK_BUF_LEN;


#ifndef FPGA_TEST
    dma_init();
#endif   
    dmx_m36f_pre_attach(&dmx_pre_attach);
    dmx_m36f_attach(&dmx_config);
#ifdef DVR_PVR_SUPPORT
    /*enable DVR feature. Only DVR proj can call this function, this function will enlarge dmx driver code size*/
    MEMSET(&dmx_config, 0, sizeof(struct dmx_feature_config));
    dmx_m36f_dvr_attach(&dmx_config);
#endif  

    if(g_cfg_para.front_end_num > 1)
        dmx_api_enhance_attach(&dmx_config);    
}


static const char *osd_devname[] = 
{
    "OSD_M3327C_0", 
    "OSD_M3327C_1",
    "OSD_M3327C_2",
};

static void ge_dev_attach(void)
{
#ifndef H264_32M_SUPPORT
	ASSERT(__MM_OSD1_LEN == __MM_OSD2_LEN);
#endif
    OSD_DRIVER_CONFIG osd_config[3];
    MEMSET((void *)&osd_config, 0, sizeof(osd_config));

    osd_config[0].uMemBase = __MM_OSD_BK_ADDR1;
    osd_config[0].uMemSize = __MM_OSD_LEN;

    osd_config[0].bStaticBlock = TRUE;//FALSE;
    osd_config[0].bDirectDraw = TRUE;
    osd_config[0].bCacheable = FALSE;

    osd_config[0].bVFilterEnable = FALSE;
    osd_config[0].bP2NScaleInNormalPlay = TRUE;
    osd_config[0].bP2NScaleInSubtitlePlay = TRUE;

    osd_config[0].uDViewScaleRatio[OSD_PAL][0] = 1;
    osd_config[0].uDViewScaleRatio[OSD_PAL][1] = 1;
    osd_config[0].uDViewScaleRatio[OSD_NTSC][0] = 576;
    osd_config[0].uDViewScaleRatio[OSD_NTSC][1] = 480;

    osd_config[1].uMemBase = __MM_OSD_BK_ADDR2;
#ifdef H264_32M_SUPPORT
#ifndef M3281_SOLUTION3_SUPPORT
	osd_config[1].uMemSize = __MM_SEE_OSD_LEN;
#else	
	/* solution 3*/
	osd_config[1].uMemSize = __MM_OSD1_LEN;
#endif
#else	
    osd_config[1].uMemSize = __MM_OSD1_LEN;
#endif
    osd_config[1].bStaticBlock = TRUE;//FALSE;
    osd_config[1].bDirectDraw = TRUE;
    osd_config[1].bCacheable = FALSE;

    osd_config[1].bVFilterEnable = FALSE;
    osd_config[1].bP2NScaleInNormalPlay = TRUE;
    osd_config[1].bP2NScaleInSubtitlePlay = TRUE;

    osd_config[1].uDViewScaleRatio[OSD_PAL][0] = 1;
    osd_config[1].uDViewScaleRatio[OSD_PAL][1] = 1;
    osd_config[1].uDViewScaleRatio[OSD_NTSC][0] = 576;
    osd_config[1].uDViewScaleRatio[OSD_NTSC][1] = 480;

    osd_config[2].uMemBase = __MM_OSD_BK_ADDR2;//not used now
#ifdef H264_32M_SUPPORT    
#ifndef M3281_SOLUTION3_SUPPORT
    osd_config[2].uMemSize = __MM_SEE_OSD_LEN;
#else    
	/* solution 3 */
	osd_config[2].uMemSize = __MM_OSD2_LEN;
#endif
#else    
    osd_config[2].uMemSize = __MM_OSD2_LEN;
#endif

    osd_config[2].bStaticBlock = TRUE;//FALSE;
    osd_config[2].bDirectDraw = TRUE;
    osd_config[2].bCacheable = FALSE;

    osd_config[2].bVFilterEnable = FALSE;
    osd_config[2].bP2NScaleInNormalPlay = TRUE;
    osd_config[2].bP2NScaleInSubtitlePlay = TRUE;

    osd_config[2].uDViewScaleRatio[OSD_PAL][0] = 1;
    osd_config[2].uDViewScaleRatio[OSD_PAL][1] = 1;
    osd_config[2].uDViewScaleRatio[OSD_NTSC][0] = 576;
    osd_config[2].uDViewScaleRatio[OSD_NTSC][1] = 480;
    
    osd_m33c_attach(osd_devname[0], &osd_config[0]);
    struct osd_device *osddev;
    osddev = (struct osd_device *)dev_get_by_name((char *)osd_devname[0]);
    osd_init_regionfill_2M(osddev);
    #ifdef DUAL_ENABLE
    osd_m33c_see_attach(osd_devname[1], &osd_config[1]);
    osddev = (struct osd_device *)dev_get_by_name((char *)osd_devname[1]);
    osd_see_init_regionfill_2M(osddev);

    #endif
    osd_config[1].uMemBase = __MM_OSD_BK_ADDR3;
    osd_config[1].uMemSize = __MM_OSD1_LEN;
    
    osd_config[1].bStaticBlock = TRUE;//FALSE;
    osd_config[1].bDirectDraw = TRUE;
    osd_config[1].bCacheable = FALSE;

    osd_config[1].bVFilterEnable = FALSE;
    osd_config[1].bP2NScaleInNormalPlay = TRUE;
    osd_config[1].bP2NScaleInSubtitlePlay = TRUE;

    osd_config[1].uDViewScaleRatio[OSD_PAL][0] = 1;
    osd_config[1].uDViewScaleRatio[OSD_PAL][1] = 1;
    osd_config[1].uDViewScaleRatio[OSD_NTSC][0] = 576;
    osd_config[1].uDViewScaleRatio[OSD_NTSC][1] = 480;

    osd_config[2].uMemBase = __MM_OSD_BK_ADDR3;//not used now
    osd_config[2].uMemSize = __MM_OSD2_LEN;

    osd_config[2].bStaticBlock = TRUE;//FALSE;
    osd_config[2].bDirectDraw = TRUE;
    osd_config[2].bCacheable = FALSE;

    osd_config[2].bVFilterEnable = FALSE;
    osd_config[2].bP2NScaleInNormalPlay = TRUE;
    osd_config[2].bP2NScaleInSubtitlePlay = TRUE;

    osd_config[2].uDViewScaleRatio[OSD_PAL][0] = 1;
    osd_config[2].uDViewScaleRatio[OSD_PAL][1] = 1;
    osd_config[2].uDViewScaleRatio[OSD_NTSC][0] = 576;
    osd_config[2].uDViewScaleRatio[OSD_NTSC][1] = 480;
    #if 1
    osd_m33c_attach("OSD_M3327C_1_M", &osd_config[1]);
    osddev = (struct osd_device *)dev_get_by_name("OSD_M3327C_1_M");
    osd_init_regionfill_2M(osddev);
	#endif
	//osd_m33c_attach(osd_devname[2], &osd_config[2]);
   // osddev = (struct osd_device *)dev_get_by_name((char *)osd_devname[2]);
   // osd_init_regionfill_2M(osddev);
	
    
};
static struct tve_adjust g_tve_adjust_table[] = {
    {TVE_ADJ_COMPOSITE_Y_DELAY, SYS_625_LINE, 2}, {TVE_ADJ_COMPOSITE_Y_DELAY, SYS_525_LINE, 3}, //3 bits
    {TVE_ADJ_COMPOSITE_C_DELAY, SYS_625_LINE, 2}, {TVE_ADJ_COMPOSITE_C_DELAY, SYS_525_LINE, 2}, //3 bits
    {TVE_ADJ_COMPONENT_Y_DELAY, SYS_625_LINE, 0x3}, {TVE_ADJ_COMPONENT_Y_DELAY, SYS_525_LINE, 0x4}, //3 bits
    {TVE_ADJ_COMPONENT_CB_DELAY, SYS_625_LINE, 2}, {TVE_ADJ_COMPONENT_CB_DELAY, SYS_525_LINE, 1}, //2 bits
    {TVE_ADJ_COMPONENT_CR_DELAY, SYS_625_LINE, 0}, {TVE_ADJ_COMPONENT_CR_DELAY, SYS_525_LINE, 3}, //2 bits
    {TVE_ADJ_BURST_LEVEL_ENABLE, SYS_625_LINE, 1}, {TVE_ADJ_BURST_LEVEL_ENABLE, SYS_525_LINE, 0}, //1 bit
    {TVE_ADJ_BURST_CB_LEVEL, SYS_625_LINE, 0x8d}, {TVE_ADJ_BURST_CB_LEVEL, SYS_525_LINE, 0x70}, //8 bits
    {TVE_ADJ_BURST_CR_LEVEL, SYS_625_LINE, 0x58}, {TVE_ADJ_BURST_CR_LEVEL, SYS_525_LINE, 0x82}, //8 bits
    {TVE_ADJ_COMPOSITE_LUMA_LEVEL, SYS_625_LINE, 0x50}, {TVE_ADJ_COMPOSITE_LUMA_LEVEL, SYS_525_LINE, 0x4b}, //8 bits
    {TVE_ADJ_COMPOSITE_CHRMA_LEVEL, SYS_625_LINE, 0x04}, {TVE_ADJ_COMPOSITE_CHRMA_LEVEL, SYS_525_LINE, 0x05}, //8 bits
    {TVE_ADJ_PHASE_COMPENSATION, SYS_625_LINE, 0x3D0}, {TVE_ADJ_PHASE_COMPENSATION, SYS_525_LINE, 0xAA}, //16 bits
    {TVE_ADJ_VIDEO_FREQ_RESPONSE, SYS_625_LINE, 0x0}, {TVE_ADJ_VIDEO_FREQ_RESPONSE, SYS_525_LINE, 0x0}, //16 bits
};

static struct tve_adjust tve_adjust_table_adv[] = {
    {TVE_ADJ_ADV_PEDESTAL_ONOFF, SYS_625_LINE, 0},              {TVE_ADJ_ADV_PEDESTAL_ONOFF, SYS_525_LINE, 1},
    {TVE_ADJ_ADV_COMPONENT_LUM_LEVEL, SYS_625_LINE, 0x52},      {TVE_ADJ_ADV_COMPONENT_LUM_LEVEL, SYS_525_LINE, 0x4D},
    {TVE_ADJ_ADV_COMPONENT_CHRMA_LEVEL, SYS_625_LINE, 0x4f},    {TVE_ADJ_ADV_COMPONENT_CHRMA_LEVEL, SYS_525_LINE, 0x50},
    {TVE_ADJ_ADV_COMPONENT_PEDESTAL_LEVEL, SYS_625_LINE, 0x0},  {TVE_ADJ_ADV_COMPONENT_PEDESTAL_LEVEL, SYS_525_LINE, 0x9},
    {TVE_ADJ_ADV_COMPONENT_SYNC_LEVEL, SYS_625_LINE, 0x0},      {TVE_ADJ_ADV_COMPONENT_SYNC_LEVEL, SYS_525_LINE, 0x0},
    {TVE_ADJ_ADV_RGB_R_LEVEL, SYS_625_LINE, 0x8d},              {TVE_ADJ_ADV_RGB_R_LEVEL, SYS_525_LINE, 0x8d},
    {TVE_ADJ_ADV_RGB_G_LEVEL, SYS_625_LINE, 0x8d},              {TVE_ADJ_ADV_RGB_G_LEVEL, SYS_525_LINE, 0x8d},
    {TVE_ADJ_ADV_RGB_B_LEVEL, SYS_625_LINE, 0x8d},              {TVE_ADJ_ADV_RGB_B_LEVEL, SYS_525_LINE, 0x8d},
    {TVE_ADJ_ADV_COMPOSITE_PEDESTAL_LEVEL, SYS_625_LINE, 0x0},  {TVE_ADJ_ADV_COMPOSITE_PEDESTAL_LEVEL, SYS_525_LINE, 0x28},
    {TVE_ADJ_ADV_COMPOSITE_SYNC_LEVEL, SYS_625_LINE, 0x0},      {TVE_ADJ_ADV_COMPOSITE_SYNC_LEVEL, SYS_525_LINE, 0x7},
};
static void vpo_dev_attach(AdvanceCfgPara* cfg_para)
{
    struct VP_Feature_Config vp_config;
    struct Tve_Feature_Config tve_config;
    struct vdec_config_par vdec_config_par;
    struct vdec_avc_config_par vdec_avc_cfg;

    MEMSET((void *)&vp_config,0,sizeof(struct VP_Feature_Config));
    MEMSET((void *)&tve_config,0,sizeof(struct Tve_Feature_Config));

    vp_config.bAvoidMosaicByFreezScr = FALSE;    /* macro VDEC_AVOID_MOSAIC_BY_FREEZE_SCR */

    vp_config.bMHEG5Enable = FALSE;                  /* macro  _MHEG5_ENABLE_ */

    vp_config.bOsdMulitLayer = TRUE;//FALSE;                  /* macro OSD_MULTI_LAYER */
    vp_config.bOvershootSolution = FALSE;            /* macro VIDEO_OVERSHOOT_SOLUTION */
    vp_config.bP2NDisableMAF= FALSE;//TRUE;
    vp_config.bSupportExtraWin = FALSE;//TRUE;                /* macro VIDEO_SUPPORT_EXTRA_DVIEW_WINDOW */
    vp_config.bADPCMEnable= FALSE;                    /* macro VIDEO_ADPCM_ONOFF(VIDEO_ADPCM_ON:TRUE VIDEO_ADPCM_OFF:FALSE) */
    vp_config.pMPGetMemInfo = NULL;
    if(NULL != cfg_para)
    {
        vp_config.pSrcAspRatioChange_CallBack = cfg_para->scart_aspect_change;//api_Scart_Aspect_Switch;
    }
    else
    {
        vp_config.pSrcAspRatioChange_CallBack = NULL;
    }

    tve_config.config = YUV_SMPTE|TVE_TTX_BY_VBI;//|TVE_NEW_CONFIG;

#ifdef SUPPORT_AFD_WSS_OUTPUT
    tve_config.config |=TVE_WSS_BY_VBI;
#endif

    tve_config.tve_adjust = g_tve_adjust_table;
    vpo_m33_attach(&vp_config, &tve_config);
    tve_advance_config(tve_adjust_table_adv);

}

static void vdec_dev_attach(void)
{
#if((!defined _S3281_)||(!defined _BUILD_OTA_E_))//add by comer
	/* !!!!!Note !!!!!
		If you copy this code to other project, please check feature configuration firstly
	     !!!!!Note !!!!!
	*/
	struct vdec_config_par vdec_config_par;

#ifdef FPGA_TEST
    return;
#endif

	MEMSET((void *)&vdec_config_par,0,sizeof(struct vdec_config_par));

	//vdec_config_par.mem_map.frm0_Y_size  = 0;
	vdec_config_par.mem_map.frm0_Y_size  = __MM_FB_LEN;
	vdec_config_par.mem_map.frm0_C_size = 0;
	vdec_config_par.mem_map.frm1_Y_size  = 0;
	vdec_config_par.mem_map.frm1_C_size = 0;
	vdec_config_par.mem_map.frm2_Y_size = 0;
	vdec_config_par.mem_map.frm2_C_size = 0;

	vdec_config_par.mem_map.frm0_Y_start_addr = __MM_FB_START_ADDR;
	vdec_config_par.mem_map.frm0_C_start_addr = 0;
	vdec_config_par.mem_map.frm1_Y_start_addr = 0;
	vdec_config_par.mem_map.frm1_C_start_addr = 0;
	vdec_config_par.mem_map.frm2_Y_start_addr = 0;
	vdec_config_par.mem_map.frm2_C_start_addr = 0;


	vdec_config_par.mem_map.dvw_frm_size = 0;
	vdec_config_par.mem_map.dvw_frm_start_addr = 0;

	vdec_config_par.mem_map.maf_size = __MM_MAF_LEN;
	vdec_config_par.mem_map.maf_start_addr = __MM_MAF_START_ADDR;
      vdec_config_par.mem_map.ext_maf_buf1 = __MM_DEVOUR_START_ADDR;
      vdec_config_par.mem_map.ext_maf_buf2 = __MM_DEVOUR_START_ADDR + 0xd00;

	vdec_config_par.mem_map.vbv_size = ((__MM_VBV_LEN-4)&0xFFFFFF00);
	vdec_config_par.mem_map.vbv_start_addr = ((__MM_VBV_START_ADDR&0xfffffff)|0x80000000);
	vdec_config_par.mem_map.vbv_end_addr = ((vdec_config_par.mem_map.vbv_start_addr) +  vdec_config_par.mem_map.vbv_size - 1);

	vdec_config_par.user_data_parsing = TRUE; /* macro USER_DATA_PARSING */
    vdec_config_par.dtg_afd_parsing = g_cfg_para.afd_scale_support;     //SUPPORT_AFD_SCALE
	vdec_config_par.drop_freerun_pic_before_firstpic_show = FALSE; /* macro VDEC27_DROP_FREERUN_BEFORE_FIRSTSHOW */
	vdec_config_par.reset_hw_directly_when_stop = TRUE;  /* macro VDEC27_STOP_REST_HW_DIRECTLY*/
	vdec_config_par.show_hd_service = FALSE;      /* macro SUPPORT_SHOW_HD_SERVICE */
	vdec_config_par.still_frm_in_cc = FALSE;          /* macro STILL_FRAME_IN_CC */
	vdec_config_par.not_show_mosaic = FALSE;      /* macro VDEC_AVOID_MOSAIC_BY_FREEZE_SCR */
	vdec_config_par.adpcm.adpcm_mode = FALSE;  /* macro VIDEO_ADPCM_ONOFF(VIDEO_ADPCM_ON:TRUE VIDEO_ADPCM_OFF:FALSE)*/
	vdec_config_par.adpcm.adpcm_ratio = 0;          
	vdec_config_par.sml_frm.sml_frm_mode = FALSE;  /* macro VDEC27_SML_FRM_ONOFF(VDEC27_SML_FRM_OFF: FALSE   VDEC27_SML_FRM_ON: TRUE)*/
	vdec_config_par.return_multi_freebuf = TRUE;        /* macro VDEC27_SUPPORT_RETURN_MULTI_FREEBUF */ 
	vdec_config_par.sml_frm.sml_frm_size = 0;           /* macro VDEC27_SML_FRM_SIZE*/
	vdec_config_par.lm_shiftthreshold = 2;                   /* macro VDEC27_LM_SHIFTTHRESHOLD*/
	vdec_config_par.vp_init_phase = 0;                        /* macro DEFAULT_MP_FILTER_ENABLE*/
	vdec_config_par.preview_solution = VDEC27_PREVIEW_DE_SCALE; /* macro VDEC27_PREVIEW_SOLUTION(VDEC27_PREVIEW_VE_SCALE or VDEC27_PREVIEW_DE_SCALE)*/
	vdec_m36_attach(&vdec_config_par);

#ifdef DVR_PVR_SUPPORT
	struct vdec_device *vdec_config_dev = (struct vdec_device *)dev_get_by_name("DECV_S3601_0");    
	vdec_enable_advance_play(vdec_config_dev);
#endif   

#ifdef HDTV_SUPPORT
    avc_attach();
#endif
#endif
}



extern UINT32 ap_get_osd_scale_param(enum TVSystem eTVMode, INT32 nScreenWidth);

static void ttx_subt_attach(void)
{
#if	(TTX_ON == 1)

	struct vbi_config_par vbi_config;
	MEMSET(&vbi_config,0,sizeof(struct vbi_config_par));

    vbi_config.ttx_by_vbi = TRUE;
	vbi_config.cc_by_vbi = FALSE;
    vbi_config.vps_by_vbi = FALSE;
	vbi_config.wss_by_vbi = FALSE;
	
	vbi_config.hamming_24_16_enable = FALSE;
	vbi_config.hamming_8_4_enable = FALSE;
    vbi_config.erase_unknown_packet = TRUE;

    if(g_cfg_para.ttx_packet_26_support)   //SUPPORT_PACKET_26
    {
        vbi_config.parse_packet26_enable = TRUE;
        vbi_config.mem_map.p26_data_buf_start_addr = __MM_TTX_P26_DATA_BUF_ADDR;
        vbi_config.mem_map.p26_data_buf_size = __MM_TTX_P26_DATA_LEN;
        vbi_config.mem_map.p26_nation_buf_start_addr = __MM_TTX_P26_NATION_BUF_ADDR;
        vbi_config.mem_map.p26_nation_buf_size = __MM_TTX_P26_NATION_LEN;
    }
    if(g_cfg_para.ttx_sub_page)          //TTX_SUB_PAGE
    {
        vbi_config.ttx_sub_page = TRUE;
        vbi_config.mem_map.sub_page_start_addr = __MM_TTX_SUB_PAGE_BUF_ADDR;
        vbi_config.mem_map.sub_page_size = __MM_TTX_SUB_PAGE_LEN;
    }


	vbi_config.user_fast_text = FALSE;	
	vbi_config.mem_map.sbf_start_addr = __MM_TTX_BS_START_ADDR;
	vbi_config.mem_map.sbf_size = __MM_TTX_BS_LEN;
	vbi_config.mem_map.pbf_start_addr = __MM_TTX_PB_START_ADDR;
	vbi_m33_attach(&vbi_config);

	struct vbi_device *vbi_config_dev = NULL;
	vbi_config_dev = dev_get_by_id(HLD_DEV_TYPE_VBI,0);	
	vbi_enable_ttx_by_osd(vbi_config_dev);
#endif

#if	(SUBTITLE_ON == 1)
#ifdef SUBT_FUNC_POINTER_ENABLE
	lib_subt_init();
#endif

	#include <api/libsubt/subt_osd.h>
	struct sdec_feature_config cfg_param;
	MEMSET(&cfg_param, 0, sizeof(struct sdec_feature_config));
	cfg_param.temp_buf_len = 0xa000;//(8*1024);  // > segment len 	
	cfg_param.temp_buf = NULL;
    cfg_param.bs_hdr_buf_len = 400;// 200;
	cfg_param.bs_hdr_buf = 0;
	cfg_param.bs_buf = (UINT8*)__MM_SUB_BS_START_ADDR;
	cfg_param.bs_buf_len = __MM_SUB_BS_LEN;
	cfg_param.pixel_buf = (UINT8*)__MM_SUB_PB_START_ADDR;

//	#ifdef OSD_BLOCKLINK_SUPPORT
//	cfg_param.pixel_buf_len = 0;
//	#else
//	cfg_param.pixel_buf_len = __MM_SUB_PB_LEN;//(100*1024)
//	#endif

	cfg_param.tsk_qtm = 2;//10;	//fix BUG05435
	cfg_param.tsk_pri = OSAL_PRI_HIGH;//OSAL_PRI_NORMAL;//OSAL_PRI_HIGH
	cfg_param.transparent_color = OSD_TRANSPARENT_COLOR;

//	#ifdef OSD_BLOCKLINK_SUPPORT
#ifdef DUAL_ENABLE
    cfg_param.sdec_hw_buf = (UINT8*)__MM_SUB_HW_DATA_ADDR;
    cfg_param.sdec_hw_buf_len = __MM_SUB_HW_DATA_LEN;
#else	
	cfg_param.subt_draw_pixel = osd_subt_draw_pixel;
	cfg_param.region_is_created = osd_region_is_created;
	cfg_param.subt_create_region = osd_subt_create_region;
	cfg_param.subt_region_show = osd_subt_region_show;
	cfg_param.subt_delete_region = osd_subt_delete_region;
#endif    
//	#else
//	cfg_param.subt_draw_pixelmap = osd_subt_draw_pixelmap;
//	#endif
    
	sdec_m33_attach(&cfg_param);
	
//	#ifdef OSD_BLOCKLINK_SUPPORT
	subt_disply_bl_init((struct sdec_device *)dev_get_by_name("SDEC_M3327_0"));
//	#else
//	subt_disply_init((struct sdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_SDEC));
//	#endif
#endif

#ifdef ATSC_SUBTITLE_SUPPORT
	struct atsc_subt_config_par atsc_subt_par;
	struct atsc_subt_config_par* patsc_subt_par=&atsc_subt_par;
	memset(&atsc_subt_par,0x00,sizeof(struct atsc_subt_config_par));

	patsc_subt_par->bs_buf_len=__MM_DCII_SUB_BS_LEN;
	patsc_subt_par->bs_buf_addr=(UINT8*)__MM_DCII_SUB_BS_START_ADDR;	
	patsc_subt_par->sec_buf_len=__MM_SUBT_ATSC_SEC_LEN;
	patsc_subt_par->sec_buf_addr=(UINT8*)__MM_SUBT_ATSC_SEC_ADDR;
	patsc_subt_par->Outline_thickness_from_stream=FALSE; //TRUE;
	patsc_subt_par->DropShadow_right_from_stream=FALSE;
	patsc_subt_par->DropShadow_bottom_from_stream=FALSE;
	patsc_subt_par->Outline_thickness=2;
	patsc_subt_par->DropShadow_right=2;
	patsc_subt_par->DropShadow_bottom=2;
	lib_subt_atsc_attach(patsc_subt_par);
#endif

//vicky20101229 dbg
#if (CC_ON==1)
	#include <api/libclosecaption/closecaption_osd.h> //vicky20110128
	struct atsc_cc_config_par cc_param;
	cc_param.pb_buf_addr=(UINT8*)__MM_ATSC_CC_PB_START_ADDR;	
	cc_param.pb_buf_len=__MM_ATSC_CC_PB_LEN;
	cc_param.bs_buf_addr=(UINT8*)__MM_ATSC_CC_BS_START_ADDR;
	cc_param.bs_buf_len=__MM_ATSC_CC_BS_LEN;
	cc_param.osd_layer_id=1;
	cc_param.cc_width=OSD_CC_WIDTH;
	cc_param.cc_height=OSD_CC_HEIGHT;
	cc_param.wPollingTime=500;		// 500ms
	cc_param.bCCScan=4;			// 4*500ms ->2sec
	cc_param.bDTVCCScan=4;		// 4*500ms ->2sec
	cc_param.osd_get_scale_para = ap_get_osd_scale_param;
	lib_atsc_cc_attach(&cc_param);	//vicky20110224
	vbi_cc_init();
#endif

#if (ISDBT_CC ==1)
	struct sdec_feature_config cc_cfg_param;	
	// fill data to [cc_cfg_param]
	MEMSET(&cc_cfg_param, 0, sizeof(struct sdec_feature_config)); //set default value of  mem as 0

	cc_cfg_param.bs_hdr_buf = 0;
	cc_cfg_param.bs_hdr_buf_len = 200;	//size under checking
	
	cc_cfg_param.bs_buf =(UINT8*)__MM_ISDBTCC_BS_START_ADDR;
	cc_cfg_param.bs_buf_len = 184*cc_cfg_param.bs_hdr_buf_len;	
	
	cc_cfg_param.tsk_qtm = 10;
	cc_cfg_param.tsk_pri = OSAL_PRI_NORMAL	;
	cc_cfg_param.transparent_color = OSD_TRANSPARENT_COLOR;
	
    	lib_isdbtcc_init();
	isdbtcc_dec_attach(&cc_cfg_param);	
	isdbtcc_disply_init((struct sdec_device *)dev_get_by_name("ISDBT_CC_0"));	
#endif

}


void smc_attach(void)
{
#if defined(SUPPORT_DVTCA)
    struct smc_dev_config smc_config;
	static UINT32 init_clk = 3570000;//4800000;
 
	MEMSET(&smc_config, 0, sizeof(struct smc_dev_config));
	smc_config.default_etu = 372;
	smc_config.def_etu_trigger = 1;
	smc_config.init_clk_trigger= 1;
	smc_config.init_clk_number = 1;
	smc_config.force_tx_rx_trigger = 1;
	smc_config.apd_disable_trigger = 1;
	smc_config.disable_pps = 0; 
	smc_config.init_clk_array = &init_clk;        
	smc_config.invert_detect = g_cfg_para.invert_detect;
	#ifndef POWER_ENJ_DEFAULT 
		//only for M3281 with no 8024  
	    smc_config.invert_power = 1;
	#endif      
	smc_dev_attach(0, &smc_config);
	return;
#else

#ifdef MULTI_CAS    
    struct smc_dev_config smc_config;
	static UINT32 init_clk = 6000000;    
	OTP_CONFIG my_otp_cfg;
    
	MEMSET(&smc_config, 0, sizeof(struct smc_dev_config));    
	MEMSET((void *)(&my_otp_cfg), 0, sizeof(OTP_CONFIG));
	otp_init(&my_otp_cfg);


	smc_config.init_clk_trigger= 1;
	smc_config.init_clk_number = 1;
	smc_config.force_tx_rx_trigger = 1;
	//smc_config.apd_disable_trigger = 1;
	//smc_config.disable_pps = 1;
    if(g_cfg_para.cas_type == CAS_CONAX)
    {
    	smc_config.def_etu_trigger = 1; 
    	smc_config.default_etu = 372;
        #ifdef CAS9_V6
        smc_config.warm_reset_trigger = 0;//v6 need all reset as cold reset
        #else
        smc_config.warm_reset_trigger = 1;
        #endif
    	smc_config.force_tx_rx_cmd = 0xdd;//CONAX command start.
    	smc_config.force_tx_rx_cmd_len = 5; //CONAX command length.	
    	init_clk = 3600000;
    	smc_config.invert_detect=0;//1;        
    }
	smc_config.init_clk_array = &init_clk;
	smc_config.class_selection_supported = 1;
	smc_config.board_supported_class = BOARD_SUPPORT_CLASS_A|BOARD_SUPPORT_CLASS_B;
	smc_config.class_select =  g_cfg_para.class_select; //board_class_select;


    smc_config.invert_detect = g_cfg_para.invert_detect;
#ifndef POWER_ENJ_DEFAULT 
//only for M3281 with no 8024  
    smc_config.invert_power = 1;
#endif
    smc_dev_attach(0, &smc_config);
#endif    

#if defined(SUPPORT_VMX_STD) || defined(_VMX_CA_ENABLE_)
    struct smc_dev_config smc_config;
	static UINT32 init_clk = 4800000;
 
	MEMSET(&smc_config, 0, sizeof(struct smc_dev_config));
	smc_config.init_clk_trigger= 1;
	smc_config.init_clk_number = 1;
	smc_config.force_tx_rx_trigger = 1;
	smc_config.apd_disable_trigger = 1;
	smc_config.disable_pps = 0; 
	smc_config.init_clk_array = &init_clk;        
	smc_config.invert_detect = g_cfg_para.invert_detect;
	smc_config.default_etu = 372;
	smc_config.def_etu_trigger = 1;
	
	#ifndef POWER_ENJ_DEFAULT 
		//only for M3281 with no 8024  
	    smc_config.invert_power = 1;
	#endif      
	smc_dev_attach(0, &smc_config);
#endif
#endif //defined(SUPPORT_DVTCA)
}



void board_advance_init(AdvanceCfgPara* cfg_para)
{
  
    if(NULL != cfg_para)
        MEMCPY(&g_cfg_para, cfg_para, sizeof(AdvanceCfgPara));

    deca_dev_attach();
    snd_dev_attach();
#ifdef _S3281_  
 	pok_attach(); //when power off ,it will stop sflash operating and mute gpio for noise for3281
#endif  
    dmx_dev_attach();
    
#ifdef CI_SUPPORT
#if (SYS_CIC_MODULE == CIMAX_27)
    struct cic_config_param cic_param = {0x86, I2C_TYPE_GPIO};
    cic_cimax_attach(&cic_param);
#else
    cic_m3602_attach();
#endif
#endif

    ge_dev_attach();
    vpo_dev_attach(cfg_para);
    vdec_dev_attach();
    ttx_subt_attach();
    smc_attach();
    
#ifdef CI_PLUS_SUPPORT
    otp_init(NULL);
#endif
    
#if defined(HDTV_SUPPORT) && (!defined(HDMI_DISABLE))

    struct config_hdmi_parm hdmi_param; 
    get_hdmi_config(&hdmi_param);
    hdmi_tx_attach(&hdmi_param);
#endif

    if(g_cfg_para.ce_api_enabled)
        ce_api_attach();
}

